package com.icerhe.trigger;


import java.util.Arrays;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.util.AttributeSet;

/**
 * A {@link Preference} 显示多选列表框
 */
public class MultiSelectPreference extends ListPreference {
	//用于分割被选择值的分隔符,其他地方用的时侯最好换个怪异点的以免冲突
	public static final String SEPARATOR = ",";
	
	//全选的选项值
	public static final String SELECT_ALL = "*";
	
	//全选时的summary字符串
	private String allCheckedSummary="";

	private boolean[] selectedValueIndices;

    public MultiSelectPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        selectedValueIndices = new boolean[getEntries().length];
    }
 
    
    
    @Override
    public void setEntries(CharSequence[] entries) {
    	super.setEntries(entries);
    	selectedValueIndices = new boolean[entries.length];
    }
    
    @Override
    public void setValue(String value) {
    	super.setValue(value);
    	refreshSummary();
    }
    
    public MultiSelectPreference(Context context) {
        this(context, null);
    }

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
    	final CharSequence[] entries = getEntries();
    	final CharSequence[] entryValues = getEntryValues();
    	
        if (entries == null || entryValues == null || entries.length != entryValues.length ) {
            throw new IllegalStateException(
                    "ListPreference requires an entries array and an entryValues array which are both the same length");
        }

        restoreCheckedEntries();

        builder.setMultiChoiceItems(entries, selectedValueIndices, 
                new DialogInterface.OnMultiChoiceClickListener() {
					public void onClick(DialogInterface dialog, int which, boolean val) {
						if (SELECT_ALL.equals(entryValues[which])) {
							//当全选按钮被选中/取消时把所有选项置为true/false
							int size = selectedValueIndices.length;
							for (int i=0; i<size; i++) {
								((AlertDialog)dialog).getListView().setItemChecked(i, val);
								selectedValueIndices[i] = val;
							}
						} else {
							selectedValueIndices[which] = val;
							if (!val) {
								//如果任意一个item被取消选中,则把全选按钮取消选中
								((AlertDialog)dialog).getListView().setItemChecked(0, false);
								selectedValueIndices[0] = false;
							} else {
								//当任意一个item被选中时检查是否所有item都被选中,如果都被选中则把全选按钮置为选中状态
								int size = selectedValueIndices.length;
								boolean status = true;
								for (int i=1; i<size; i++) {
									if (!selectedValueIndices[i]) {
										status = false;
										break;
									}
								}
								((AlertDialog)dialog).getListView().setItemChecked(0, status);
								selectedValueIndices[0] = status;
							}
						}
					}
        });
    }

    public static String[] parseStoredValue(CharSequence val) {
		if ( val==null || "".equals(val) )
			return null;
		else
			return ((String)val).split(SEPARATOR);
    }
    
    private void restoreCheckedEntries() {
    	CharSequence[] entryValues = getEntryValues();
    	
    	if (SELECT_ALL.equals(getValue())) {
    		Arrays.fill(selectedValueIndices, true);
    		return;
    	}
    	
    	String[] vals = parseStoredValue(getValue());
    	if ( vals != null ) {
        	for ( int j=0; j<vals.length; j++ ) {
        		String val = vals[j].trim();
            	for ( int i=0; i<entryValues.length; i++ ) {
                	if ( entryValues[i].equals(val) ) {
                		selectedValueIndices[i] = true;
            			break;
            		}
            	}
        	}
    	}
    }

	@Override
    protected void onDialogClosed(boolean positiveResult) {
		CharSequence[] entrys = getEntries();
    	CharSequence[] entryValues = getEntryValues();
        if (positiveResult && entryValues != null) {	
        	if (allTrue(selectedValueIndices) || allFalse(selectedValueIndices)) {
        		setValue(SELECT_ALL);
        		setSummary(allCheckedSummary);
        		callChangeListener(SELECT_ALL);
        		return;
        	}
        	
        	StringBuffer entry = new StringBuffer();
        	StringBuffer value = new StringBuffer();
        	for ( int i=0; i<entryValues.length; i++ ) {
        		if ( selectedValueIndices[i] ) {
        			value.append(entryValues[i]).append(SEPARATOR);
        			entry.append(entrys[i]).append(SEPARATOR);
        		}
        	}
        	
        	String ety = entry.toString();
        	String val = value.toString();
        	if ( val.length() > 0 )
        		val = val.substring(0, val.length()-SEPARATOR.length());
        	if ( ety.length()>0)
        		ety = ety.substring(0, ety.length()-SEPARATOR.length());
        	setValue(val);
        	setSummary(ety);
        	
            callChangeListener(value);
        }
    }

	private void refreshSummary() {
		restoreCheckedEntries();
		CharSequence[] entrys = getEntries();
    	CharSequence[] entryValues = getEntryValues();
    	
    	if (allTrue(selectedValueIndices)) {
    		setSummary(allCheckedSummary);
    		return;
    	}
    	
    	StringBuffer entry = new StringBuffer("");
    	for ( int i=0; i<entryValues.length; i++ ) {
    		if ( selectedValueIndices[i] ) {
    			entry.append(SEPARATOR).append(entrys[i]);
    		}
    	}
    	
    	String ret = entry.toString();
    	if (ret.length()>0) ret = ret.substring(1);
    	
    	setSummary(ret);
	}
	
	private static boolean allTrue(boolean[] ary) {
		for(int i=0; i<ary.length; i++) {
			if (ary[i]==false) return false;
		}
		return true;
	}
	
	private static boolean allFalse(boolean[] ary) {
		for(int i=0; i<ary.length; i++) {
			if (ary[i]==true) return false;
		}
		return true;
	}
	
    public String getAllCheckedSummary() {
		return allCheckedSummary;
	}

	public void setAllCheckedSummary(String allCheckedSummary) {
		this.allCheckedSummary = allCheckedSummary;
	}
}
